Clases genéricas en C#
Más de C#. En este post toca hablar sobre los genéricos
Los genéricos, y más concretamente en este post los tipos genéricos, son un mecanismo de C# que nos ayuda a maximizar la reutilización de código. La reutilización de código se logra a través de el uso de plantillas (templates) de código en las cuales se insertan marcadores (placeholders) que representarán los tipos de dato que usaremos en nuestra plantilla.
Sintaxis
La declaración de tipos genéricos se realiza casi como cualquier otro tipo, con la diferencia de que tenemos que declarar los placeholders entre signos <
y >
, por ejemplo,
En la cual le estamos indicando que usaremos un marcador llamado T
. Que se lee como “Box de T”. Luego entonces dentro de la declaración de la clase podemos reutilizar el marcador T
tantas veces como queramos:
Para hacer uso de un tipo genérico la sintaxis es más o menos igual a cualquier tipo por referencia: debemos usar el operador new
, el constructor de la clase e indicarle dentro de <
y >
los tipos con los que queremos que se reemplaze el marcador.
También podemos anidar declaraciones en los tipos genéricos:
No hay “límite” en cuanto al nombre o cantidad de tipos que podemos usar, por ejemplo:
Restricción where
De entrada, si solo especificamos de esta manera Box<T>
los genéricos, podríamos crear objetos a partir de Box
sin limitacio
Es por eso que usando la cláusula where X : [Condición] podemos limitar qué tipo de datos aceptará nuestro tipo genérico como marcadores, por ejemplo, supongamos que tenemos las clases:
Estamos limitando a que:
LimitedBox<T>
únicamente acepte enT
, tipos que seanstruct
comodecimal
yDateTime
LimitedBox<X0, X1>
únicamente acepte enX0
, tipos que seanstruct
comodecimal
yDateTime
y enX1
objetos que implementen la interfazIEquatable
LimitedBox<T, U, V>
similar al anterior, solo que en el tercer parámetro,V
, únicamente aceptará objetos que tengan un constructor vacío que se a público
La lista completa de restricciones se encuentra en este enlace.
Ejemplos
Pero bueno, veamos un ejemplo.
Imaginate un programa para gestionar un deportivo, en el que existen equipos de futbol y de béisbol, compuestos por atletas, Athlete
, (que a su vez se divide en futbolistas, FootballPlayer
, y por beisbolistas, BaseballPlayer
):
Ahora, para crear los equipos podríamos tener clases separadas para representar cada equipo:
Y para crear equipos tendríamos que hacer algo así:
Genéricos
O, para maximizar la reutilización de código, podríamos crear una clase genérica, digamos Team<T>
(“Team de T”), para poder reutilizarla (y no solo con equipos de futbol o beisbol):
Y usarlo de esta manera:
Si dejamos la clase Team<T>
como está, podríamos hacer cosas como esta:
Que tal vez no tienen mucho sentido en nuestra aplicación. Es por eso que usando la restricción where
podemos limitar al tipo Team<T>
para que únicamente acepte Athlete
s:
Ejemplos del Framework
En el Framework .NET existen numerosos ejemplos de tipos genéricos, siendo el más usado y conocido, las colecciones genéricas y las tuplas en C#.
Para cerrar
Usar los genéricos permiten dos cosas: Incrementar la reutilización de código manteniendo el tipado fuerte y reducir el impacto al desempeño en nuestras apps al evitar el boxing y unboxing, de ahí la importancia de su existencia.
Además, los genéricos existen también para métodos, post sobre el que estaré escribiendo en el futuro.